# Автогенерация api для RTK Query, graphql, postgraphile и postgresql

Дисклеймер: код испольуемый в данной статье предназначен исключительно для демонстрационных целей.

Исходный код можно найти [ здесь ](https://gitverse.ru/eustatos/learn-graphile)

Предусловие:

- имеется GraphQL API сервер. В данном примере, его адрес: `http://localhost:5001/graphql`. Он реализован с помощью `postgraphile`. Его настройка и запуск описаны ниже.

Клиентское приложение создадим на основе `vitejs` и `react`

```
npm create vite@latest client -- --template react-ts
```

Для автогенерации api RTK Query предоставляет плагин [@graphql-codegen/typescript-rtk-query](https://the-guild.dev/graphql/codegen/plugins/typescript/typescript-rtk-query)

Для его использования нам понадобится еще несколько пакетов. Для этого в директории нашего клиентского приложения выполним:

```
npm i -D @graphql-codegen/cli \
@graphql-codegen/introspection \
@graphql-codegen/near-operation-file-preset \
@graphql-codegen/typescript-rtk-query \
@rtk-query/graphql-request-base-query
```

В разделе `scripts` в `package.json` добавим:

```
    "graphql-codegen": "graphql-codegen --config codegen.yml"
```

Теперь в корне директории нашего клиентского приложения добавим файл настроек для автогенерации `codegen.yaml`:

```yaml
overwrite: true
schema: "http://localhost:5001/graphql"
documents: "src/**/*.graphql"
watchConfig:
  usePolling: true
  interval: 1000
generates:
  src/app/services/types.generated.ts:
    plugins:
      - typescript
    config:
      maybeValue: T # normally, this would be T | null, but our msw mock returns everything as nullable, so we want to force these as non-nullalbe
  src/:
    preset: near-operation-file
    presetConfig:
      baseTypesPath: app/services/types.generated.ts
    plugins:
      - add:
          content: >
            /* eslint-disable */
            /**
             *
             * THIS FILE IS AUTOGENERATED, DO NOT EDIT IT!
             *
             * instead, edit one of the `.graphql` files in this project and run
             *
             * npm run graphql-codegen
             *
             * for this file to be re-created
             */
      - typescript-operations
      - typescript-rtk-query:
          importBaseApiFrom: "../../app/services/baseApi"
          exportHooks: true
    config:
      maybeValue: T # normally, this would be T | null, but our msw mock returns everything as nullable, so we want to force these as non-nullalbe
  .introspection.json:
    plugins:
      - introspection
```

После этого нужно проверить наличие в директории `src` файлов, содержащих запросы qraphql: query, mutation.
В этом примере, это файлы в директории `src/features/todos`:

```
src/features/todos
├── createTodo.graphql
├── deleteTodo.graphql
├── getTodos.graphql
└── updateTodoById.graphql
```

Также следует убедиться, что сервер работает и находится по адресу, указанному в конфигурации.
Создадим файл `src/app/services/baseApi.ts` следующего содержания:

```typescript
import { createApi } from "@reduxjs/toolkit/query/react";
import { graphqlRequestBaseQuery } from "@rtk-query/graphql-request-base-query";
import { GraphQLClient } from "graphql-request";

export const client = new GraphQLClient("/api/graphql");

export const api = createApi({
  baseQuery: graphqlRequestBaseQuery({ client }),
  endpoints: () => ({}),
});
```

В папке `src/features/todos` добавим файлы graphql запросов:
`createTodo.graphql`

```graphql
mutation createTodo($description: String = "") {
  createTodo(input: { todo: { description: $description } }) {
    todo {
      description
      id
    }
  }
}
```

`getTodos.graphql`

```graphql
query getTodos {
  allTodos {
    nodes {
      id
      description
      completed
    }
  }
}
```

`deleteTodo.graphql`

```graphql
mutation deleteTodoById($id: Int = 10) {
  deleteTodoById(input: { id: $id }) {
    todo {
      description
      id
    }
  }
}
```

После этого выполним:

```
npm run graphql-codegen
```

Вывод команды при успешном выполнении:

```
> client@0.0.0 graphql-codegen
> graphql-codegen --config codegen.yml

✔ Parse Configuration
✔ Generate outputs
```

В результате выполнения должны сгенерироваться следующие файлы:

```
src
├── app
│   └── services
│       └── types.generated.ts
└── features
    └── todos
        ├── createTodo.generated.ts
        ├── deleteTodo.generated.ts
        ├── getTodos.generated.ts
        └──updateTodoById.generated.ts
```

Пример использования можно посмотреть [ здесь ](https://gitverse.ru/eustatos/learn-graphile)

Для этого в директории проекта выполните:

```
docker-compose up -d
```

А затем в директории `/client`:

```
npm run dev
```
